package keer.httpinterface.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@SuppressWarnings("unchecked")
/**
 * JdkHttpInterfaceProxyFactory类是用于创建HTTP接口代理的工厂，它继承自CacheableHttpInterfaceProxyFactory类
 * 该类的主要作用是利用JDK的动态代理机制来创建指定接口的代理实例
 * @see ProxyFactory
 * @see CacheableHttpInterfaceProxyFactory
 * @see keer.httpinterface.proxy.CacheableHttpInterfaceProxyFactory.InvokeCallback
 *
 * @author Keer
 * @since 1.0.0
 */
public class JdkHttpInterfaceProxyFactory extends CacheableHttpInterfaceProxyFactory {

    /**
     * 创建一个指定接口的调用器
     *
     * @param targetClass 目标接口的类类型
     * @param callback 调用回调接口，用于处理实际的调用逻辑
     * @param <T> 目标接口的类型
     * @return 返回一个目标接口类型的代理实例
     * @throws Exception 如果创建过程中出现异常，则抛出此异常
     */
    @Override
    protected <T> T createInvoker(Class<T> targetClass, InvokeCallback callback) throws Exception {
        // 使用JDK动态代理创建目标接口的代理实例
        return (T) Proxy.newProxyInstance(targetClass.getClassLoader(),
                new Class[]{targetClass},
                new JdkHttpInterfaceInvocationHandler(callback));
    }

    /**
     * JdkHttpInterfaceInvocationHandler类实现了InvocationHandler接口，
     * 它用于处理代理实例的方法调用
     */
    private static class JdkHttpInterfaceInvocationHandler implements InvocationHandler {
        // 调用回调接口，用于实际的方法调用
        private final InvokeCallback callback;

        /**
         * 构造函数，初始化调用回调接口
         *
         * @param callback 调用回调接口实例
         */
        private JdkHttpInterfaceInvocationHandler(InvokeCallback callback) {
            this.callback = callback;
        }

        /**
         * 处理代理实例的方法调用
         *
         * @param proxy 代理实例
         * @param method 被调用的方法
         * @param args 方法参数
         * @return 返回方法调用的结果
         * @throws Throwable 如果方法调用过程中出现异常，则抛出此异常
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 调用回调接口的doInvoke方法来执行实际的方法调用
            return callback.doInvoke(proxy, method, args);
        }

    }
}
